﻿using System;
using System.Collections.Generic;

namespace Sustainalytics.Caching
{
    public static class IAppCacheExtensions
    {
        public static void Set(this IAppCache cache, string key, object value)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new CacheItemKeyNullOrEmptyException();
            }

            if (value is string)
            {
                cache.Set(key, (string)value);
            }
            else
            {
                if (value is IEnumerable<string>)
                {
                    cache.Set(key, (IEnumerable<string>)value);
                }
                else
                {
                    throw new CacheItemTypeNotSupportedException();
                }
            }
        }

        public static void Set(this IAppCache cache, string key, byte[] value)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new CacheItemKeyNullOrEmptyException();
            }

            if (value == null)
            {
                return;
            }

            string valueAsStr = Convert.ToBase64String(value);

            cache.Set(key, valueAsStr);
        }

        public static byte[] GetBytes(this IAppCache cache, string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new CacheItemKeyNullOrEmptyException();
            }

            string value = cache.GetString(key);

            if (value == null)
                return null;

            byte[] valueAsBytes = Convert.FromBase64String(value);

            return valueAsBytes;
        }

        public static void PullFromCache(this IAppCache thisCache, IAppCache otherCache, bool addExistingData = false)
        {
            otherCache.Subscribe(cacheItemAction =>
                {
                    switch (cacheItemAction.ActionType)
                    {
                        case AppCacheItemActionType.Set:
                            thisCache.Set(cacheItemAction.CacheItem.Key, cacheItemAction.CacheItem.Value);
                            break;
                        case AppCacheItemActionType.Removed:
                            thisCache.Remove(cacheItemAction.CacheItem.Key);
                            break;
                    }
                });
        }

        public static void PushToCache(this IAppCache thisCache, IAppCache otherCache, bool addExistingData = false)
        {
            otherCache.PullFromCache(thisCache, addExistingData);
        }

        public static void SyncWithCache(this IAppCache thisCache, IAppCache otherCache, bool addExistingData = false)
        {
            thisCache.PullFromCache(otherCache, addExistingData);
            thisCache.PushToCache(otherCache, addExistingData);
        }
    }
}
